import httpx

from utils.ja3_factory import AsyncJA3Transport
from items import RequestItem, TransportItem, ResponseItem
from .base import Base


class AsyncCrawler(Base):
    @classmethod
    async def request(cls, request_item: RequestItem, retry_times=1) -> ResponseItem:
        """

        :param request_item: RequestItem
        :param retry_times: 重试次数
        :return: ResponseItem
        """
        self = cls()

        proxy = self.get_proxy(request_item)

        transport_item = TransportItem(http2=request_item.http2, proxy=proxy)
        transport = AsyncJA3Transport(**transport_item.dict())
        async with httpx.AsyncClient(transport=transport) as client:
            try:
                r = await client.request(
                    **request_item.dict(
                        exclude={
                            "proxies",
                            "http2",
                            "meta",
                            "parse_callback",
                            "data_callback",
                        }
                    )
                )
            except self.retry_exception as e:
                if retry_times >= self.retry_times:
                    response_item = self.error_response(request_item, e)
                else:
                    return await self.request(request_item, retry_times + 1)
            except Exception as e:
                response_item = self.error_response(request_item, e)
            else:
                response_item = self.success_response(request_item, r)
        return response_item
